package edu.snake.implement.command.snake;


import edu.snake.core.controller.ArenaController.Direction;
import edu.snake.core.controller.GameEngine;
import edu.snake.core.controller.command.Algorithm;
import edu.snake.core.model.Character;
import edu.snake.core.model.Character.CharacterName;
import edu.snake.implement.command.AbstractCommand;
import edu.snake.implement.controller.character.SnakeController;

import java.util.Deque;

import static edu.snake.implement.factory.CharacterControllerFactory.getNewSnakeElement;

public class SnakeMove extends AbstractCommand implements Algorithm {


    public SnakeMove(SnakeController controller) {
        super(controller);
    }

    @Override
    public void action() {
        Direction direction = controller.getDirection();
        GameEngine gameEngine = controller.getGameEngine();
        Character snake = controller.getModel();
        Deque<Character> characterList = snake.getAllElement();

        Character newSnakeElement = getNewSnakeElement(snake.getPosition());

        Character collisionCharacter = arenaController.setToArenaWithMove(snake, direction);
        newSnakeElement.setPosition(snake.getPosition());
        if (collisionCharacter == null) {
            characterList.addLast(newSnakeElement);
            arenaController.setToArena(characterList.getFirst().getPosition(), null);
            characterList.removeFirst();
        } else {
            if (collisionCharacter.getName().equals(CharacterName.FROG)) {
                while (collisionCharacter != null) {
                    int score = collisionCharacter.getScore();
                    gameEngine.incrementScore(score);
                    gameEngine.killCharacter(collisionCharacter);

                    Character collisionCharacter01 = arenaController.setToArenaWithMove(snake, direction);  //ещвщ надо быть уверенным что произошла 100%  setToArenaWithMove
                    newSnakeElement.setPosition(snake.getPosition());
                    characterList.addLast(newSnakeElement);
                    growSnake(score);
                    collisionCharacter = collisionCharacter01;
                    //                todo если произошла коллизия то setToArenaWithDirection не произошло нужно убить контроллер очистить модель контроллера,
// очистить арену и заново выполнить setToArenaWithMove or setToArena
//                Лягушки едятся сейчас! но нет конца игры когда коллизия со змеюй и бордюром.
                }

            } else if (collisionCharacter.getName().equals(CharacterName.BORDER) ||
                    collisionCharacter.getName().equals(CharacterName.SNAKE)) {
                controller.getGameEngine().stopGame();
            }
        }
    }

    private void growSnake(int score) {
        Deque<Character> characterDeque = controller.getModel().getAllElement();
        switch (score) {
            case 1:
                break;
            case 2:
                if (characterDeque.size() > controller.getModel().getScore()+1) {
                    arenaController.setToArena(characterDeque.getFirst().getPosition(), null);
                    characterDeque.removeFirst();//todo incapsulate deque????
                    arenaController.setToArena(characterDeque.getFirst().getPosition(), null);
                    characterDeque.removeFirst();//todo incapsulate deque????
                } else {
                    arenaController.setToArena(characterDeque.getFirst().getPosition(), null);
                    characterDeque.removeFirst();//todo incapsulate deque????
                }
                break;
            default:
                arenaController.setToArena(characterDeque.getFirst().getPosition(), null);
                characterDeque.removeFirst();//todo incapsulate deque????
        }
    }
}
